package com.szy.redstonemcu;

import com.szy.assembly.Assembler;
import com.szy.assembly.CPUSimulator;
import com.szy.assembly.GPIO;
import com.szy.assembly.Timer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;

public class MessageHandlerOnServer implements IMessageHandler<McuMessage, IMessage> {

    @Override
    public IMessage onMessage(McuMessage message, MessageContext ctx) {
        if (ctx.side != Side.SERVER) {
            System.err.println("ClientToServer received on wrong side:" + ctx.side);
            return null;
        }


        // we know for sure that this handler is only used on the server side, so it is ok to assume
        //  that the ctx handler is a serverhandler, and that WorldServer exists.
        // Packets received on the client side must be handled differently!  See MessageHandlerOnClient

        final EntityPlayerMP sendingPlayer = ctx.getServerHandler().player;
        if (sendingPlayer == null) {
            System.err.println("EntityPlayerMP was null when AirstrikeMessageToServer was received");
            return null;
        }

        // This code creates a new task which will be executed by the server during the next tick,
        //  for example see MinecraftServer.updateTimeLightAndEntities(), just under section
        //      this.theProfiler.startSection("jobs");
        //  In this case, the task is to call messageHandlerOnServer.processMessage(message, sendingPlayer)
        final WorldServer playerWorldServer = sendingPlayer.getServerWorld();
        playerWorldServer.addScheduledTask(new Runnable() {
            public void run() {
                processMessage(message, sendingPlayer);
            }
        });

        return null;
    }
    void processMessage(McuMessage message, EntityPlayerMP player)
    {
        RedstoneMCU.logger.info("server receive message, type="+message.typeNum);
        WorldServer world = player.getServerWorld();
        if(message.typeNum == McuMessage.TYPE_ASSEMBLE_CODE){
            BlockPos pos=new BlockPos(message.pos);
            TileEntity entity = world.getTileEntity(pos);
            if (entity instanceof McuBaseEntity){
                McuBaseEntity te=(McuBaseEntity)entity;
                //RedstoneMCU.logger.info("server task,code:"+message.code);
                Assembler assembler=new Assembler(te.codeText);
                if(assembler.assemble()){
                    RedstoneMCU.logger.info("build successfully");
                    te.simulator=new CPUSimulator(assembler.getProgram(),256,te.getPeripherals());
                    te.peripherals.clear();
                    te.peripherals.add(new GPIO(0x08000000).setIoChangedNotifier(te).setInterruptRequester(te.simulator));
                    te.peripherals.add(new Timer(0x08001000).setIoChangedNotifier(te).setInterruptRequester(te.simulator));
                    RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT,"build successfully"),player);
                }else{
                    RedstoneMCU.logger.info(assembler.getErrorList());
                    RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT, assembler.getErrorList().get(0).toString()),player);
                }
            }
        }else if(message.typeNum == McuMessage.TYPE_RESET_RUN){
            BlockPos pos=new BlockPos(message.pos);
            TileEntity entity = world.getTileEntity(pos);
            if (entity instanceof McuBaseEntity) {
                McuBaseEntity te = (McuBaseEntity) entity;
                RedstoneMCU.logger.info("server task,run");
                te.simulator.restartPeriodically();
                RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT,"Running"),player);
            }
        }else if(message.typeNum == McuMessage.TYPE_SAVE_CODE){
            BlockPos pos=new BlockPos(message.pos);
            TileEntity entity = world.getTileEntity(pos);
            if (entity instanceof McuBaseEntity) {
                McuBaseEntity te=(McuBaseEntity) entity;
                te.codeText= message.code;
            }
        }else if(message.typeNum == McuMessage.TYPE_PAUSE){
            BlockPos pos=new BlockPos(message.pos);
            TileEntity entity = world.getTileEntity(pos);
            if (entity instanceof McuBaseEntity) {
                McuBaseEntity te = (McuBaseEntity) entity;
                RedstoneMCU.logger.info("server task,pause");
                te.simulator.pause();
                //把断点告诉ui



                RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT,"Pause at\n"+te.simulator.getCurrentInstruction().getOriginalText()),player);
            }
        }else if(message.typeNum == McuMessage.TYPE_RESUME){
            BlockPos pos=new BlockPos(message.pos);
            TileEntity entity = world.getTileEntity(pos);
            if (entity instanceof McuBaseEntity) {
                McuBaseEntity te = (McuBaseEntity) entity;
                RedstoneMCU.logger.info("server task,resume");
                te.simulator.resume();
                RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT,"Running"),player);
            }
        }else if(message.typeNum == McuMessage.TYPE_REQUEST_GUI){
            BlockPos pos=new BlockPos(message.pos);
            TileEntity entity = world.getTileEntity(pos);
            if (entity instanceof McuBaseEntity) {
                McuBaseEntity te = (McuBaseEntity) entity;
                RedstoneMCU.logger.info("server task,request gui");
                RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_READ_CODE,te.codeText),player);
                if(te.simulator.runningState()){
                    RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT,"Running"), player);
                }else{
                    RedstoneMCU.simpleNetworkWrapper.sendTo(new McuMessage(pos, McuMessage.TYPE_RETURN_ASSEMBLE_RESULT,"Pause at\n"+te.simulator.getCurrentInstruction().getOriginalText()),player);
                }
            }
        }


    }
}
